//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================
#include <mantle.h>
#include <idmanage.h>
#include <svrobj.h>

oid_t g_curOid = 1;

static SLinkNode  s_hashObject[CFG_OID2OBJ_HS];

EXTERN_C DECL_CODEINIT void CDECL InitObjectHash()
{
    for (int i = 0; i < CFG_OID2OBJ_HS; i++) {
        s_hashObject[i].Initialize();
    }
}

#ifdef DEBUG_KMUTEX
KMutex g_objectLock(__FILE__, __LINE__);
#else
KMutex g_objectLock;
#endif //DEBUG_KMUTEX

oid_t GenerateObjOid()
{
    oid_t ret = InterlockedIncrement((Int32 *)&g_curOid);
    if (ret == 0xFFFF0000) g_curOid = 0x10000;
    return ret;
}

void  AddObject(Object * pObject)
{
    assert(!IS_FAKE_OID(pObject->m_oid));
    g_objectLock.Lock();
    s_hashObject[pObject->m_oid \
        & HASH2MASK(CFG_OID2OBJ_HS)].InsertNext((SLinkNode *)pObject);
    g_objectLock.Unlock();
}

ECode  DeleteObject(oid_t oid)
{
    g_objectLock.Lock();
    SLinkNode * pSLinkNode;
    SLinkNode * pHead;
    SLinkNode * pSLinkPrev;

    pHead =  &s_hashObject[oid & HASH2MASK(CFG_OID2OBJ_HS)];
    pSLinkPrev = pHead;
    pSLinkNode = pHead->Next();

    while (pSLinkNode != pHead) {
        Object * p = (Object *)pSLinkNode;
        if (p->m_oid == oid) {
            pSLinkNode->Detach(pSLinkPrev);
            g_objectLock.Unlock();
            if (p->m_pNameHook) {
                NameHook::Destroy(p->m_pNameHook);
            }
            free(p);
            return NOERROR;
        }
        pSLinkPrev = pSLinkNode;
        pSLinkNode = pSLinkNode->Next();
    }

    g_objectLock.Unlock();
    return E_DOES_NOT_EXIST;
}

Object * GetObject(oid_t oid)
{
    g_objectLock.Lock();
    SLinkNode * pSLinkNode;
    SLinkNode * pHead;

    pHead =  &s_hashObject[oid & HASH2MASK(CFG_OID2OBJ_HS)];
    pSLinkNode = pHead->Next();

    while (pSLinkNode != pHead) {
        Object * pObject = (Object *)pSLinkNode;
        if (pObject->m_oid == oid) {
            g_objectLock.Unlock();
            return pObject;
        }
        pSLinkNode = pSLinkNode->Next();
    }

    g_objectLock.Unlock();
    return NULL;
}

// Destroy all objects and NameHooks created by the Process
//
ECode  DeleteObjects(CProcess * pCProcess)
{
    SLinkNode * pSLinkNode;
    SLinkNode * pHead;
    SLinkNode * pSLinkPrev;
    int i;

    assert(pCProcess);
    g_objectLock.Lock();
    for (i = 0; i < CFG_OID2OBJ_HS; i++) {
        pHead =  &s_hashObject[i];
        pSLinkPrev = pHead;
        pSLinkNode = pHead->Next();

        while (pSLinkNode != pHead) {
            Object * p = (Object *)pSLinkNode;
            if (p->m_pCProcess == pCProcess) {
                pSLinkNode->Detach(pSLinkPrev);
                if (p->m_pNameHook) {
                    NameHook::Destroy(p->m_pNameHook);
                }
                free(p);
                pSLinkNode = pSLinkPrev;
            }
            pSLinkPrev = pSLinkNode;
            pSLinkNode = pSLinkNode->Next();
        }
    }
    g_objectLock.Unlock();

    return NOERROR;
}
